#include "level1.hpp"
#include <Shinygami/soundmanager.hpp>

#include "control_config.hpp"

using namespace Shiny;
using namespace Shiny::Applejack;

void Level1::AddPlayer(int numPlayer, const std::string &name, Controls& controls)
{
    Body*   body = Body::Factory::New(_world, name, sf::Vector2f((numPlayer == 0 ? 140.f : 770.f), 500.f), 0.f);
    Player* script;

    if (name == "michael")
	script = new FighterMichael(_world, *body, _players[numPlayer].camera);
    else if (name == "louis")
	script = new FighterLouis(_world, *body, _players[numPlayer].camera);
    else if (name == "alex")
	script = new FighterAlex(_world, *body, _players[numPlayer].camera);
    else if (name == "yann")
	script = new FighterYann(_world, *body, _players[numPlayer].camera);

    _players[numPlayer].player = body;
    _players[numPlayer].script = script;
    body->SetIA(script);
    if (_players[numPlayer].lifebar)
      script->LifeUpdated.Connect(*(_players[numPlayer].lifebar), &Widgets::ProgressBar::SetPercentage);

    script->SetControls(controls);

    for (int i = 0 ; i < _countPlayers ; ++i)
    {
      if (_players[i].player == 0)
	return ;
    }
    for (int i = 0 ; i < _countPlayers ; ++i)
    {
      std::stringstream stream;

      stream << "Player" << (i + 1);
      _players[i].player->SetName(stream.str());
      for (int ii = 0 ; ii < _countPlayers ; ++ii)
      {
	if (ii != i)
	  _players[i].script->AddTarget(_players[ii].script, _players[ii].player->Fixture("body"), &Player::GetKicked);
      }
      _players[i].camera->SyncWithBody(_players[i].player, 50, sf::Vector2f(-1.f, -1.f));
    }
}

void Level1::SetScreenSize(const sf::Vector2f& size)
{
    for (unsigned char i = 0 ; i < _countPlayers ; ++i)
    {
	sf::Vector2f cameraSize, position;

	_players[i].camera = reinterpret_cast<Shiny::Applejack::View*>(_world.CreateView());
	if (i != 2 || (i == 2 && _countPlayers == 4))
	  cameraSize.x = size.x / 2;
	else
	  cameraSize.x = size.x;
	cameraSize.y   = (_countPlayers < 3 ? size.y : size.y / 2);
	position.y     = (i == 0 || i == 1  ? 0.f    : size.y / 2);
	position.x     = (i == 0 || i == 2  ? 0.f    : size.x / 2);
	_players[i].camera->SetSize(cameraSize);
	_players[i].camera->SetPosition(position);
	_world.AddView(_players[i].camera);
    }
}

Level1::Level1(World& world, int countPlayers) : Module(world), _countPlayers(countPlayers)
{
    _hud = world.Hud();
    if (_hud)
    {
	_players[0].lifebar = _hud->GetWidget<Widgets::ProgressBar>("lifePlayer1");
	_players[1].lifebar = _hud->GetWidget<Widgets::ProgressBar>("lifePlayer2");
	_players[2].lifebar = _hud->GetWidget<Widgets::ProgressBar>("lifePlayer3");
	_players[3].lifebar = _hud->GetWidget<Widgets::ProgressBar>("lifePlayer4");
	for (int i = countPlayers ; i < 4 ; ++i)
	  _players[i].lifebar->ForceVisibility(false);
    }
    else
    {
	ErrorManager::Get()->AddError("Can't load the HUD", ErrorManager::StopLevel);
	return ;
    }
    _hud->ForceVisibility(false);
    _hud->SetVisible(true);
    _victoryText = 0;

    MusicManager* musicmanager = MusicManager::Get();

    if (musicmanager)
    {
      musicmanager->Load("music/RevolutionVoid-UrbanReflection.wav");
      musicmanager->Play("music/RevolutionVoid-UrbanReflection.wav");
    }

    DataBranch* nada = new DataBranch;
    Data        controlData(nada);

    controlData["Leaving"]["Key"] = "Escape";
    _controls.LoadData(controlData);
    Shiny::EventManager::Get()->Controls().Add(_controls);
}

  void Level1::FightOver(const std::string& text)
  {
      _victoryText = new Widgets::TextWidget;
      _victoryText->SetText(text);
      _victoryText->SetAlign(Widgets::Center, Widgets::VCenter);
      _hud->AddWidget(_victoryText);

      if (_controls["Leaving"])
	_controls["Leaving"]->Released.Connect(*this, &Level1::ExitLevel);
      else
	ExitLevel(sf::Event());
  }

  void Level1::ExitLevel(sf::Event)
  {
      EndLevel.Emit(true);
  }

  void Level1::ManageHits()
  {

  }

void Level1::Run(void)
{
    char countDefeated = 0;

    for (char i = 0 ; i < _countPlayers ; ++i)
    {
	if (!_players[i].defeated && _players[i].lifebar->Percentage() == 0)
	{
	  _players[i].defeated = true;
	  _players[i].script->Victory(false);
	}
	if (_players[i].defeated)
	  countDefeated++;
    }
    if (!_victoryText)
    {
	if      (countDefeated == _countPlayers)
	      FightOver("Tie");
	else if (countDefeated == _countPlayers - 1)
	{
	    for (char i = 0 ; i < _countPlayers ; ++i)
	    {
	      if (_players[i].defeated == false)
	      {
		      FightOver(_players[i].player->Name() + " wins");
		      _players[i].script->Victory(true);
		      break ;
	      }
	    }
	}
    }
}
